home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS16.ADF
/
C
/
InputHandler
/
in.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-01-27
|
12KB
|
431 lines
/*
Input handler for use with TxEd.
This module will only work with MANX C because it does two things.
1. It has inline assembly code that uses manx directives
2. It assumes the manx SMALL data/code memory model.
Point 2 is crucial. In order to use the Manx library, register A4 must be
set prior to calling any runtime library routines such as permit() and forbid().
So, the first thing done in the main routine is to call a small assembler
fragment (_GetA4) that returns the current value of A4. This is stored in a
global variable (_mya4) so that when the input handler gets called (its called
as an interrupt handler in the context of the input device and not the context
of the rest of the program) register A4 must be set prior to calling any C
code. See _HandlerInterface at the bottom of this module.
Note that although the small code/data model is assumed (so that A4 will be
set up properly at the beginning of function main) the assembly code must
use large code/data and is thus placed at the end of the file. It must use
the large model so that the instruction that loads A4 from _mya4 uses absolute
addressing instead of an offset to A4 (which isn't set up yet - thats what
the code does!!).
*/
#include <exec/types.h>
#include <exec/ports.h>
#define function /* this is just used by the indenter */
#define then {
#define elsif } else if
#define els } else {
#define fi }
#define forever for (;;) {
#define rof }
#define or ||
#define and &&
#define not !
#define NIL 0L
#define z if(1==0)
#include <devices/timer.h>
#include <exec/memory.h>
/* #include <exec/io.h> */
/* #include <exec/tasks.h> */
#include <exec/interrupts.h>
#include <devices/input.h>
#include <exec/devices.h>
#include <devices/inputevent.h>
#define gev(the__ev,v_code,v_qual,v_link) the__ev.ie_NextEvent = v_link; \
the__ev.ie_Class = IECLASS_RAWKEY; \
/* the__ev.ie_SubClass = 0; */ \
the__ev.ie_Code = v_code; \
the__ev.ie_Qualifier = v_qual; \
/* the__ev.ie_X = 0; */ \
/* the__ev.ie_Y = 0; */ \
/* the__ev.ie_TimeStamp.tv_secs = 0; */ \
/* the__ev.ie_TimeStamp.tv_micro = 0; */
#define ctime(the__ev,e_v) \
the__ev.ie_TimeStamp.tv_secs=e_v->ie_TimeStamp.tv_secs;\
the__ev.ie_TimeStamp.tv_micro=e_v->ie_TimeStamp.tv_micro;
struct InputEvent copyevent;
struct InputEvent ev_b1= 0; /* to create a right-amiga-B sequence */
struct InputEvent ev_b2= 0;
struct InputEvent ev_c1= 0; /* to create a right-amiga-C sequence */
struct InputEvent ev_c2= 0;
struct InputEvent ev_x1= 0; /* to create a right-amiga-X sequence */
struct InputEvent ev_x2= 0;
struct InputEvent ev_i1= 0; /* to create a right-amiga-I sequence */
struct InputEvent ev_i2= 0;
struct InputEvent ev_d1= 0; /* to create a right-amiga-d sequence */
struct InputEvent ev_d2= 0;
struct InputEvent ev_u1= 0; /* to create a right-amiga-u sequence */
struct InputEvent ev_u2= 0;
struct InputEvent ev_t1= 0; /* to create a right-amiga-t sequence */
struct InputEvent ev_t2= 0;
struct InputEvent ev_f1= 0; /* to create a right-amiga-f sequence */
struct InputEvent ev_f2= 0;
struct MsgPort *inputDevPort;
struct IOStdReq *inputRequestBlock;
struct Interrupt handlerStuff;
struct InputEvent dummyEvent;
struct MsgPort *CreatePort();
struct IOStdReq *CreateStdIO();
struct MemEntry me[10];
struct timerequest *PrepareTimer();
extern long OpenDevice();
extern Enable_Abort;
extern long SysBase;
int hcount = 0;
long int p1,p2,p3;
static char str_buf[BUFSIZ]; /* used for buffered i/o to terminal */
int enable_cut_paste = 1;
int exit_now = 0;
function struct InputEvent *myhandler(ev,mydata) register struct InputEvent *ev; struct MemEntry *mydata[]; {
struct InputEvent *ret;
register int evQ,evC;
ret = ev;
p3 = SysBase;
hcount++; p1 = (long)ev; p2 = (long)mydata;
if(ev->ie_Class == IECLASS_TIMER) then
return ret;
els
evQ = ev->ie_Qualifier;
evC = ev->ie_Code;
if( ev->ie_Class == IECLASS_RAWKEY ) then
if( (evC == 0x60 or evC == 0x61) and evQ == 0x8003) then
enable_cut_paste = 1 - enable_cut_paste ;
elsif (evC == 0xe1 and evQ == 0x8009) then
enable_cut_paste = 0;
exit_now = 1;/* right shift up with ctrl and left shift down */
fi
fi
Forbid(); /* keyboard and our interceptions */
if (enable_cut_paste and ev->ie_Class == IECLASS_RAWKEY ) then
if ((evQ == 0x8010 or evQ == 0xc010) and evC == 0x64) then /* left alt down */
ret = &ev_b1;
elsif ((evQ == 0x8000 or evQ == 0xc000) and evC == 0xe4) then /* l alt up */
ret = &ev_c1;
elsif (evQ == 0x8040 and evC == 0x66) then /* l amiga down */
ret = NULL;
elsif (evQ == 0x8000 and evC == 0xe6) then /* l amiga up */
ret = &ev_i1;
elsif (evQ == 0x8011 and evC == 0x64) then /* shift l alt down */
ret = &ev_b1;
elsif (evQ == 0x8001 and evC == 0xe4) then /* shift l alt up */
ret = &ev_x1;
elsif (( evQ == 0x8000 or evQ == 0x8200) and evC == 0x50) then /* f1 down */
ret = &ev_d1;
elsif (( evQ == 0x8000 or evQ == 0x8200) and evC == 0x51) then /* f2 down */
ret = &ev_u1;
elsif (( evQ == 0x8000 or evQ == 0x8200) and evC == 0x55) then /* f2 down */
ret = &ev_f1;
elsif ( evQ == 0x8000 and evC == 0x52) then /* f3 down */
ret = &ev_t1;
fi
fi
Permit();
fi
return ret;
}
extern struct Task *FindTask();
struct Task *mytask;
LONG mysingnal;
extern VOID HandlerInterface();
struct timerequest *mytimerRequest;
extern struct timerequest *PrepareTimer();
extern long int WaitTimer();
extern void DeleteTimer();
extern VOID ewindow();
struct IntuitionBase *IntuitionBase;
extern struct IntuitionBase *OpenLibrary();
LONG my_a4 = 0; extern LONG GetA4();
function void main(argc,argv) int argc; char **argv; {
long error;
ULONG oldseconds,oldmicro,oldclass;
IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",0L);
if ( IntuitionBase == NULL) then
return;
fi
my_a4 = GetA4(); /* need current base for interrupt handler */
gev(ev_b1,0x35,0x8080,&ev_b2); /* set up an amiga-b */ /* b down */
gev(ev_b2,0xb5,0x8080,NULL ); /* b up */
gev(ev_i1,0x17,0x8080,&ev_i2); /* set up an amiga-i */
gev(ev_i2,0x97,0x8080,NULL );
gev(ev_x1,0x32,0x8080,&ev_x2); /* set up an amiga-x */
gev(ev_x2,0xb2,0x8080,NULL );
gev(ev_c1,0x33,0x8080,&ev_c2); /* set up an amiga-c */
gev(ev_c2,0xb3,0x8080,NULL );
gev(ev_d1,0x22,0x8080,&ev_d2); /* set up an amiga-d */
gev(ev_d2,0xa2,0x8080,NULL );
gev(ev_u1,0x16,0x8080,&ev_u2); /* set up an amiga-u */
gev(ev_u2,0x96,0x8080,NULL );
gev(ev_t1,0x14,0x8080,&ev_t2); /* set up an amiga-t */
gev(ev_t2,0x94,0x8080,NULL );
gev(ev_f1,0x23,0x8080,&ev_f2); /* set up an amiga-f */
gev(ev_f2,0xa3,0x8080,NULL );
dummyEvent.ie_Class = IECLASS_NULL;
dummyEvent.ie_NextEvent = NULL;
inputDevPort = CreatePort(0L,0L);
if(inputDevPort == NULL) then
ewindow("Can't open input device",NIL);
exit(-1);
fi
inputRequestBlock = CreateStdIO(inputDevPort);
if (inputRequestBlock == NULL) then
DeletePort(inputDevPort);
ewindow("Can't CreateStdIO",NIL);
exit(-2);
fi
mytimerRequest = PrepareTimer(1);
if (mytimerRequest == NULL) then
ewindow("Can't init timer",NIL);
exit(-3);
fi
handlerStuff.is_Data = (APTR) &me[0];
handlerStuff.is_Code = HandlerInterface;
handlerStuff.is_Node.ln_Pri= 127;
error = OpenDevice("input.device",0L,inputRequestBlock,0L);
if (error != NULL ) then
ewindow("Can't open input.device",NIL);
exit(-4);
fi
inputRequestBlock->io_Command = IND_ADDHANDLER;
inputRequestBlock->io_Data = (APTR) &handlerStuff;
DoIO(inputRequestBlock);
copyevent.ie_TimeStamp.tv_secs = 0;
copyevent.ie_TimeStamp.tv_micro = 0;
copyevent.ie_Class = 0;
oldseconds = 0;
oldmicro = 0;
oldclass = 0;
Enable_Abort = 0;
forever
WaitForTimer(mytimerRequest,0L,100000L); /* 1/10'th second */
if (exit_now) then /* check for exit */
break;
fi
rof
inputRequestBlock->io_Command = IND_REMHANDLER;
inputRequestBlock->io_Data = (APTR) &handlerStuff;
DoIO(inputRequestBlock);
if (IntuitionBase) CloseLibrary(IntuitionBase);
CloseDevice(inputRequestBlock);
DeleteStdIO(inputRequestBlock);
DeletePort(inputDevPort);
DeleteTimer(mytimerRequest);
}
function showEvents(e) struct InputEvent *e; {
}
extern struct MsgPort *CreatePort();
extern struct IORequest *CreateExtIO();
function struct timerequest *PrepareTimer(precision) register SHORT precision; {
register long int error; register long whichunit;
register struct MsgPort *timerport;
register struct timerequest *timermsg;
timerport = CreatePort(0L,0L);
if (timerport == NULL) then
/* printf("no port\n"); */
return NULL;
fi
timermsg =(struct timerequest *) CreateExtIO(timerport,(long)sizeof(struct timerequest));
if (timermsg == NULL) then
/* printf("no timermsg\n"); */
DeletePort(timerport);
return NULL;
fi
if (precision) then
whichunit = UNIT_MICROHZ;
els
whichunit = UNIT_VBLANK;
fi
error = OpenDevice(TIMERNAME,whichunit,timermsg,0L);
if (error != NULL) then
/* printf("opendevice = %ld\n",error); */
DeleteExtIO(timermsg,sizeof(struct timerequest));
DeletePort(timerport);
return NULL;
fi
return timermsg;
}
function WaitForTimer(tr,seconds,microseconds)
ULONG seconds,microseconds; register struct timerequest *tr; {
tr->tr_node.io_Command = TR_ADDREQUEST;
tr->tr_time.tv_secs = seconds;
tr->tr_time.tv_micro = microseconds;
DoIO(tr);
return 0;
}
function VOID ewindow(str, parm) char *str; char *parm;
{
ewindow_int(str,parm,0);
}
function bwindow(str, parm) char *str; char *parm;
{
return ewindow_int(str,parm,1);
}
function long between(a,b,c)
register long a,b,c;
{
if (b <= a) then
return a;
elsif (b >= c) then
return c;
fi
return b;
}
function static short int ewindow_int(str, parm,bool) char *str; char *parm; short int bool;
{
static struct IntuiText t3 = { 2,1,0,5,3,NULL,(UBYTE *)"CANCEL",NULL };
static struct IntuiText t2 = { 2,1,0,5,3,NULL,(UBYTE *)"Ok",NULL };
static struct IntuiText t1 = { 2,1,0,15,7,NULL,NULL,NULL };
char mess[86];
register struct IntuiText *pt;
extern long AutoRequest(),IntuiTextLength();
if (bool) then
pt = &t3;
els
pt = &t2;
fi
mess[0] = '\0';
strncat(mess,str,80);
strncat(mess," ",80);
strncat(mess,parm,80);
mess[79] = '\0';
t1.IText = (UBYTE *) mess;
return (short int) AutoRequest(NIL,&t1,&t2,pt,NIL,NIL,
between(150L,(long) IntuiTextLength(&t1)+65L,639L),50L);
}
function void DeleteTimer(tr) register struct timerequest *tr; {
register struct MsgPort *tp;
tp = tr->tr_node.io_Message.mn_ReplyPort;
if (tr != 0) then
CloseDevice(tr);
DeleteExtIO(tr,sizeof(struct timerequest));
fi
if (tp != 0) then
DeletePort(tp);
fi
return ;
#ifndef _lint
#asm
;-------------------------------------------------------------------------
; MAKE SURE THIS ASSEMBLY CODE IS AT THE END OF THIS C SOURCE FILE
;-------------------------------------------------------------------------
far code ;make sure the below can load a4 without using a4
far data ;ditto
_HandlerInterface:
movem.l saver,-(sp)
move.l _my_a4,a4
movem.l a0/a1,-(a7)
jsr _myhandler
addq.l #8,a7
movem.l (sp)+,saver
rts
saver: reg a0-a6/d1-d7
_GetA4:
move.l a4,d0
rts
#endasm
#endif
}